﻿using System;
using System.Collections.Generic;
using System.Globalization;
using Monkey.Framework.Logging;
using Monkey.Warrenty.Bo;
using Monkey.Warrenty.Data;
using Monkey.Warrenty.Data.Interfaces;
using Monkey.Warrenty.EntityModel;
using Monkey.Warrenty.Enum;
using MonkeyWarranty.Models.TicketModels;

namespace Monkey.Warrenty.Biz
{
    public class InstantTicketBiz
    {
        #region Properties

        private const string DateFormat = "dd/MM/yyyy";

        private readonly IInstantTicketDao _instantTicketDao;
        private readonly IEmployeeDao _employeeDao;
        private readonly ICustomerDao _customerDao;
        private readonly IInstantTicketStatusDao _instantTicketStatusDao;

        #endregion

        #region Constructors

        public InstantTicketBiz()
        {
            _instantTicketDao = new InstantTicketDao();
            _employeeDao = new EmployeeDao();
            _customerDao = new CustomerDao();
            _instantTicketStatusDao = new InstantTicketStatusDao();
        }

        public InstantTicketBiz(IInstantTicketDao instantTicketDao, IEmployeeDao employeeDao, ICustomerDao customerDao, IInstantTicketStatusDao instantTicketStatusDao)
        {
            _instantTicketDao = instantTicketDao;
            _employeeDao = employeeDao;
            _customerDao = customerDao;
            _instantTicketStatusDao = instantTicketStatusDao;
        }

        #endregion

        #region Selection Methods

        public long GetNextCode()
        {
            return _instantTicketDao.GetCurrentIdentity() + 1;
        }

        public long GetMaxId()
        {
            // TODO: try catch
            return _instantTicketDao.GetMaxId();
        }

        public List<Employee> GetEmployees()
        {
            return _employeeDao.GetAllEmployees();
        }

        public InstantTicket GetById(long id)
        {
            return id <= 0 ? null : _instantTicketDao.GetById(id);
        }

        public object GetTicketsWs(int jtStartIndex, int jtPageSize, string jtSorting, int status)
        {
            var ticketCount = _instantTicketDao.GetTicketCountByFilter(status);
            var instantTicketViews = _instantTicketDao.GetTicketViews(jtStartIndex, jtPageSize, jtSorting, status);

            foreach (var instantTicketView in instantTicketViews)
            {
                instantTicketView.CreatedTimeString = string.Format("{0:HH:mm}", instantTicketView.CreatedDate);
            }

            return new { Result = "OK", Records = instantTicketViews, TotalRecordCount = ticketCount };
        }

        public int GetTicketCount(InstantTicketStatus ticketStatus)
        {
            return _instantTicketDao.GetTicketCountByFilter((int)ticketStatus);
        }

        public List<InstantTicketState> GetTicketStates()
        {
            return _instantTicketStatusDao.GetAllTicketStates();
        }

        public int SearchTicketsCount(InstantSearchModel searchModel)
        {
            DateTime createdDateFrom, createdDateTo;
            if (!string.IsNullOrEmpty(searchModel.CreatedDateFromString) &&
                DateTime.TryParseExact(searchModel.CreatedDateFromString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out createdDateFrom))
            {
                searchModel.CreatedDateFrom = createdDateFrom;
            }
            if (!string.IsNullOrEmpty(searchModel.CreatedDateToString) &&
                DateTime.TryParseExact(searchModel.CreatedDateToString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out createdDateTo))
            {
                searchModel.CreatedDateTo = createdDateTo;
            }

            return _instantTicketDao.SearchTicketsCount(searchModel);
        }

        public List<InstantTicketView> SearchTickets(InstantSearchModel searchModel)
        {
            DateTime createdDateFrom, createdDateTo;
            if (!string.IsNullOrEmpty(searchModel.CreatedDateFromString) &&
                DateTime.TryParseExact(searchModel.CreatedDateFromString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out createdDateFrom))
            {
                searchModel.CreatedDateFrom = createdDateFrom;
            }
            if (!string.IsNullOrEmpty(searchModel.CreatedDateToString) &&
                DateTime.TryParseExact(searchModel.CreatedDateToString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out createdDateTo))
            {
                searchModel.CreatedDateTo = createdDateTo;
            }

            return _instantTicketDao.SearchTickets(searchModel);
        }

        #endregion

        #region

        public InstantTicket CreateTicket(InstantTicket ticket, Customer customer)
        {
            // check new or existed customer
            //if (customer.Id == 0)
            //{
            //    // create new customer
            //    customer = _customerDao.AddCustomer(customer);
            //}

            // get customer code
            if (customer.Id == 0)
            {
                var maxCustomerId = _customerDao.GetMaxId();
                customer.Code = string.Format("{0:00000}", maxCustomerId + 1);
                customer = _customerDao.AddCustomer(customer);
            }

            // create instant ticket
            ticket.CustomerId = customer.Id;
            _instantTicketDao.AddTicket(ticket);

            return ticket;
        }
        
        public void UpdateTicket(InstantTicket ticket)
        {
            if (ticket == null) return;

            _instantTicketDao.UpdateTicket(ticket);
        }

        public void DeleteTicket(long id)
        {
            if (id <= 0) throw new ApplicationException("InvalidTicket");

            _instantTicketDao.DeleteTicket(id);
        }

        public long CopyToWarranty(long id)
        {
            return id <= 0 ? 0 : _instantTicketDao.CopyToWarraty(id);
        }

        #endregion

        #region Ticket Product Methods

        public InstantTicket_Product CreateTicketProduct(InstantTicket_Product ticketProduct)
        {
            if (ticketProduct == null || ticketProduct.ProductId <= 0) return null;

            _instantTicketDao.CreateTicketProduct(ticketProduct);

            return null;
        }

        public List<InstantTicketProductView> GetTicketProducts(long ticketId)
        {
            if (ticketId <= 0) return null;

            return _instantTicketDao.GetTicketProducts(ticketId);
        }

        public void DeleteTicketProduct(long ticketProductId)
        {
            if (ticketProductId <= 0) return;
            _instantTicketDao.DeleteTicketProduct(ticketProductId);
        }

        public InstantTicket_Product GetTicketProductById(long id)
        {
            return id <= 0 ? null : _instantTicketDao.GetTicketProductById(id);
        }

        public void UpdateTicketProduct(InstantTicket_Product ticketProduct)
        {
            if (ticketProduct == null) return;

            _instantTicketDao.UpdateTicketProduct(ticketProduct);
        }

        public InstantTicket_Product CreateTicketService(InstantTicket_Service ticketService)
        {
            if (ticketService == null || ticketService.ServiceId <= 0) return null;

            _instantTicketDao.CreateTicketService(ticketService);

            return null;
        }

        public List<InstantTicketServiceView> GetTicketServices(long ticketId)
        {
            if (ticketId <= 0) return null;

            return _instantTicketDao.GetTicketServices(ticketId);
        }

        public void DeleteTicketService(long ticketServiceId)
        {
            if (ticketServiceId <= 0) return;
            _instantTicketDao.DeleteTicketService(ticketServiceId);
        }

        public InstantTicket_Service GetTicketServiceById(long id)
        {
            return id <= 0 ? null : _instantTicketDao.GetTicketServiceById(id);
        }

        public void UpdateTicketService(InstantTicket_Service ticketService)
        {
            if (ticketService == null) return;

            _instantTicketDao.UpdateTicketService(ticketService);
        }

        public InstantTicket_Employee CreateTicketEmployee(InstantTicket_Employee ticketEmployee)
        {
            if (ticketEmployee == null || ticketEmployee.InstantTicketId <= 0) return null;

            return _instantTicketDao.CreateTicketEmployee(ticketEmployee);
        }

        #endregion

        #region Employee Methods

        public List<InstantTicketEmployeeView> GetTicketEmployees(long ticketId)
        {
            if (ticketId <= 0) return null;

            var results = _instantTicketDao.GetTicketEmployees(ticketId);
            foreach (var result in results)
            {
                result.StartTimeString = string.Format("{0:HH:mm}", result.StartDate);
            }

            return results;
        }

        public void DeleteTicketEmployee(long ticketEmployeeId)
        {
            if (ticketEmployeeId <= 0) return;
            _instantTicketDao.DeleteTicketEmployee(ticketEmployeeId);
        }

        public InstantTicket_Employee GetTicketEmployeeById(long id)
        {
            return id <= 0 ? null : _instantTicketDao.GetTicketEmployeeById(id);
        }

        public void UpdateTicketEmployee(InstantTicket_Employee ticketEmployee)
        {
            if (ticketEmployee == null) return;

            _instantTicketDao.UpdateTicketEmployee(ticketEmployee);
        }

        #endregion

        #region For printing

        public List<InstantTicketPrintBo> GetInstantTicketForPrint(long id)
        {
            if (id <= 0) return null;

            var tickets = new List<InstantTicketPrintBo>
                              {
                                  _instantTicketDao.GetInstantTicketForPrint(id)
                              };
            return tickets;
        }

        public List<TaskServiceBo> GetInstantTicketTaskServiceDetails(long id)
        {
            return id <= 0 ? null : _instantTicketDao.GetInstantTicketTaskServiceDetails(id);
        }

        #endregion

        #region For Reporting

        public List<InstantTicketEmployeeCount> GetInstantTicketEmployeeCount(DateTime dateFrom, DateTime dateTo)
        {
            try
            {
                return _instantTicketDao.GetInstantTicketEmployeeCount(dateFrom, dateTo);
            }
            catch (Exception ex)
            {
                LoggingFactory.GetLogger().Log(ex.ToString());
                return new List<InstantTicketEmployeeCount>();
            }
        }

        #endregion

        #region Helpers
        #endregion

        public int SearchServicesCount(InstantServiceSearchModel searchModel)
        {
            DateTime startDateFrom, startDateTo;
            if (!string.IsNullOrEmpty(searchModel.StartDateFromString) &&
                DateTime.TryParseExact(searchModel.StartDateFromString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateFrom))
            {
                searchModel.StartDateFrom = startDateFrom;
            }
            if (!string.IsNullOrEmpty(searchModel.StartDateToString) &&
                DateTime.TryParseExact(searchModel.StartDateToString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateTo))
            {
                searchModel.StartDateTo = startDateTo;
            }

            return _instantTicketDao.SearchServicesCount(searchModel);
        }

        public List<InstantTicketServiceView> SearchServices(InstantServiceSearchModel searchModel)
        {
            DateTime startDateFrom, startDateTo;
            if (!string.IsNullOrEmpty(searchModel.StartDateFromString) &&
                DateTime.TryParseExact(searchModel.StartDateFromString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateFrom))
            {
                searchModel.StartDateFrom = startDateFrom;
            }
            if (!string.IsNullOrEmpty(searchModel.StartDateToString) &&
                DateTime.TryParseExact(searchModel.StartDateToString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateTo))
            {
                searchModel.StartDateTo = startDateTo;
            }

            return _instantTicketDao.SearchServices(searchModel);
        }

        public int SearchProductsCount(InstantProductSearchModel searchModel)
        {
            DateTime startDateFrom, startDateTo;
            if (!string.IsNullOrEmpty(searchModel.StartDateFromString) &&
                DateTime.TryParseExact(searchModel.StartDateFromString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateFrom))
            {
                searchModel.StartDateFrom = startDateFrom;
            }
            if (!string.IsNullOrEmpty(searchModel.StartDateToString) &&
                DateTime.TryParseExact(searchModel.StartDateToString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateTo))
            {
                searchModel.StartDateTo = startDateTo;
            }

            return _instantTicketDao.SearchProductsCount(searchModel);
        }

        public object SearchProducts(InstantProductSearchModel searchModel)
        {
            DateTime startDateFrom, startDateTo;
            if (!string.IsNullOrEmpty(searchModel.StartDateFromString) &&
                DateTime.TryParseExact(searchModel.StartDateFromString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateFrom))
            {
                searchModel.StartDateFrom = startDateFrom;
            }
            if (!string.IsNullOrEmpty(searchModel.StartDateToString) &&
                DateTime.TryParseExact(searchModel.StartDateToString, DateFormat, CultureInfo.InvariantCulture,
                DateTimeStyles.None, out startDateTo))
            {
                searchModel.StartDateTo = startDateTo;
            }

            return _instantTicketDao.SearchProducts(searchModel);
        }

        public void UpdateTicketServiceStatus(long instantServiceId, int statusId, string description, string note)
        {
            if (instantServiceId <= 0) return;
            _instantTicketDao.UpdateTicketServiceStatus(instantServiceId, statusId, description, note);
        }

        public List<InstantTicketServiceView> GetActiveTicketServiceViews(Employee employee)
        {
            if (employee == null) return null;
            if (employee.HasRole("Admin") || employee.HasRole("Admin_DichVu"))
            {
                // get all active
                return _instantTicketDao.GetActiveTicketServiceViews(0);
            }
            return _instantTicketDao.GetActiveTicketServiceViews(employee.Id);
        }

        public List<InstantTicketProductView> GetActiveTicketProductViews(Employee employee)
        {
            if (employee == null) return null;
            if (employee.HasRole("Admin") || employee.HasRole("Admin_DichVu"))
            {
                // get all active
                return _instantTicketDao.GetActiveTicketProductViews(0);
            }
            return _instantTicketDao.GetActiveTicketProductViews(employee.Id);
        }

        public void UpdateTicketProductStatus(long instantProductId, int statusId, string description, string note)
        {
            if (instantProductId <= 0) return;
            _instantTicketDao.UpdateTicketProductStatus(instantProductId, statusId, description, note);
        }
    }
}
